<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>虚拟dom</title>
</head>
<body>
  <div id="root">
    <div class="c1">
      <div title="tt1" id="id">hello1</div>
      <div title="tt2">hello2</div>
      <div title="tt3">hello3</div>
      <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
      </ul>
    </div>
  </div>
  <script>
  class VNode {
    constructor (tag, data, value, type) {
      this.tag = tag && tag.toLowerCase();
      this.data = data;
      this.value = value;
      this.type = type;
      this.children = []
    }
    appendChild(vnode) {
      this.children.push(vnode)
    }
  }
  function getVNode( node ) {
    const nodeType = node.nodeType
    let _node = null
    if (nodeType === 1) { // 元素节点
      const nodeName = node.nodeName // 获取元素标签
      const attrs = node.attributes // 获取元素属性 伪数组
      const objAttrs = {}
      // 循环
      for (let i = 0;  i < attrs.length; i++) {
        objAttrs[attrs[i].nodeName] = attrs[i].nodeValue
      }
      _node = new VNode(nodeName, objAttrs, undefined, nodeType)
      // 节点下面还有节点
      const childNode = node.childNodes
      for ( let i = 0; i < childNode.length; i++ ) {
        _node.appendChild( getVNode(childNode[i]) ) // 递归
      }
    } else if (nodeType === 3){ // 文本节点
      _node = new VNode(undefined, undefined, node.textContent, nodeType)
    }
    return _node
  }
  // 将 vNode 转换为真正的 DOM ( 作业 )
  function parseVNode( vnode ) {
    const nodeType = vnode.type
    let _node = null;
    if (nodeType === 3) { // 是文本
      return document.createTextNode(vnode.value)
    } else if (nodeType === 1) {// 是节点
      _node = document.createElement(vnode.tag)
      // 获取节点属性
      const data = vnode.data
      Object.keys(data).forEach(key => {
        const attrValue = data[key]
        _node.setAttribute(key , attrValue)
      })
      const children = vnode.children
      children.forEach(subvnode => {
        _node.appendChild( parseVNode( subvnode ) )
      })
      return _node
    }
  }
  const root = document.querySelector('#root')
  const result = getVNode(root)
  let getDom = parseVNode(result)
  const parentNode = root.parentNode
  // 删除原来的
  parentNode.removeChild(root)
  // 替换新的
  parentNode.appendChild(getDom)
  </script>
</body>
</html>